
function _openDB(dbKey){
    return auDataBase.created(dbKey).then((db)=>{
        if(db){
            return db;
        }
        return new Promise((resolve, reject) => {
            let request = window.indexedDB.open(dbKey);
            request.onsuccess=e=>{
                resolve(e.target.result);
            };
            request.onerror=reject
        })
    })
}


//复杂查询辅助函数
function _with(obj,js){
    return new Function(`{${Object.keys(obj).join(",")}}`,'row',`return ${js}`)(obj,obj);
}
function _where(data,where){
    if(!where){
        return true;
    }
    try{
        if(typeof where==="string"){
            //判断
            return _with(data,where);
        }else if(where instanceof Array){
            let keys=Object.keys(where);
            for (const i in keys) {
                let key=keys[i];
                let it=where[key];
                if(!_with(data,it)){
                    return false
                }
            }
        }
    }catch (e){
        return false;
    }
    return true;
}

//数据库操作
class auDataBase{
    constructor(dbKey) {
        this.dbKey=dbKey;
    }
    //添加
    add(data){
        return auDataBase.add(this.dbKey,data);
    }
    //添加或更新
    put(data){
        return auDataBase.put(this.dbKey,data);
    }
    //合并对象或添加
    merge(data){
        return auDataBase.merge(this.dbKey,data);
    }
    mergeList(dataList){
        return auDataBase.merge(this.dbKey,dataList);
    }
    //添加
    addList(dataList){
        return auDataBase.merge(this.dbKey,dataList);
    }
    //添加或更新
    putList(dataList){
        return auDataBase.merge(this.dbKey,dataList);
    }
    //根据存储空间的键找到对应数据
    findDataByKey(keyOrKeys){
        return auDataBase.findDataByKey(this.dbKey,keyOrKeys);
    }
    //获取全部数据 ，根据 storename
    findAllData(){
        return auDataBase.findAllData(this.dbKey);
    }
    //复杂查询
    find(query){
        return auDataBase.find(this.dbKey,query)
    }
    //删除数据
    delete(id){
        return auDataBase.delete(this.dbKey,id)
    }
    deleteList(ids){
        return auDataBase.deleteList(this.dbKey,ids)
    }
    remove(){
        return auDataBase.remove(this.dbKey)
    }

    //获取数据库列表
    static database(){
        return indexedDB.databases()
    }
    //获取条数
    static count(dbKey){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            return new Promise((resolve, reject) => {
                let request = store.count();
                request.onerror = function (e) {
                    db.close();
                    reject(new Error(e.message))
                };
                request.onsuccess = function (e) {
                    db.close();
                    resolve(e.target.result);
                };
            })
        })
    }
    //添加修改
    static add(dbKey,data){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            return new Promise((resolve, reject) => {
                let request = store.add(data);
                request.onerror = function () {
                    db.close();
                    reject(new Error("添加数据库中已有该数据"))
                };
                request.onsuccess = function () {
                    db.close();
                    resolve();
                };
            })
        })
    }
    static put(dbKey,data){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            return new Promise((resolve, reject) => {
                let request = store.put(data);
                request.onerror = function () {
                    db.close();
                    reject(new Error("添加数据库中已有该数据"))
                };
                request.onsuccess = function () {
                    db.close();
                    resolve();
                };
            })
        })
    }
    static merge(dbKey,data){
        return _openDB(dbKey).then((db)=>{
            //获取id
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let keyPath=store.keyPath;
            if(!data[keyPath]){
                return Promise.reject(new Error("没有找到"+keyPath))
            }
            let id=data[keyPath]
            return new Promise((resolve, reject) => {
                let request=store.get(id);
                request.onsuccess=function(){
                    let obj={
                        ...request.result,
                        ...data
                    };
                    store.put(obj);
                    db.close();
                    resolve(obj);
                }
                request.onerror=(err)=>{
                    db.close();
                    reject(err)
                };
            })
        })
    }
    static addList(dbKey,dataList){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let list=[];
            if(!(dataList instanceof Array)){
                dataList=[dataList];
            }
            dataList.forEach(x=>{
                list.push(new Promise((resolve, reject) => {
                    let request = store.add(x);
                    request.onerror = function () {
                        reject(new Error("添加数据库中已有该数据"))
                    };
                    request.onsuccess = function () {
                        resolve(x);
                    };
                }))
            })
            return Promise.all(list).then(()=>db.close()).catch(db.close())
        })
    }
    static putList(dbKey,dataList){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let list=[];
            if(!(dataList instanceof Array)){
                dataList=[dataList];
            }
            dataList.forEach(x=>{
                list.push(new Promise((resolve, reject) => {
                    let request = store.put(x);
                    request.onerror = function () {
                        reject(new Error("添加数据库中已有该数据"))
                    };
                    request.onsuccess = function () {
                        resolve(x);
                    };
                }))
            })
            return Promise.all(list).then(()=>db.close()).catch(db.close())
        })
    }
    static mergeList(dbKey,dataList){
        return _openDB(dbKey).then((db)=>{
            //获取id
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let keyPath=store.keyPath;
            let list=[];
            dataList.forEach(data=>{
                list.push(new Promise((resolve, reject) => {
                    if(!data[keyPath]){
                        return resolve();
                    }
                    let id=data[keyPath]
                    let request=store.get(id);
                    request.onsuccess=function(){
                        let obj={
                            ...request.result,
                            ...data
                        };
                        store.put(obj);
                        resolve(obj);
                    }
                    request.onerror=(err)=>{
                        reject(err)
                    };
                }))
            })
            return Promise.all(list).then(()=>db.close()).catch(db.close())
        })
    }

    //查询
    static findDataByKey(dbKey,keyOrKeys){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let list=[];
            if(!(keyOrKeys instanceof Array)){
                keyOrKeys=[keyOrKeys];
            }
            keyOrKeys.forEach(key=>{
                list.push(new Promise((resolve, reject) => {
                    let request = store.get(key);
                    request.onerror = function () {
                        db.close()
                        reject(new Error("添加数据库中已有该数据"))
                    };
                    request.onsuccess = function (e) {
                        let result = e.target.result;
                        db.close()
                        resolve(result);
                    };
                }))
            })
            return Promise.all(list).then(x=>x[0])
        })
    }
    static findAllData(dbKey){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let data=[];
            let request = store.openCursor();
            return new Promise((resolve, reject) => {
                request.onerror = function () {
                    db.close()
                    reject(new Error("查询错误"));
                };
                request.onsuccess = function (e) {
                    let result = e.target.result;
                    if (result && result !== null) {
                        data.push(result.value);
                        result.continue();
                    } else {
                        db.close()
                        resolve(data);
                    }
                };
            })
        })
    }
    static find(dbKey,query={}){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let data=[];
            let request = store.openCursor();
            let {where,sort,page,pageSize}=query;

            return new Promise((resolve, reject) => {
                request.onerror = function () {
                    db.close()
                    reject(new Error("查询错误"));
                };

                request.onsuccess = function (e) {
                    db.close()
                    let result = e.target.result;
                    if (result && result !== null) {
                        if(_where(result.value,where)){
                            data.push(result.value);
                        }
                        result.continue();
                    } else {
                        console.log('全部查找数据成功')
                        resolve(data);
                    }
                };
            }).then(x=>{
                //排序
                if(!sort || !sort.key || !sort.type){
                    return x;
                }
                let {key,type}=sort;
                return x.sort((a,b)=>{
                    if(type==="desc"){
                        return _with(b,key)-_with(a,key)
                    }else{
                        return _with(a,key)-_with(b,key)
                    }
                });
            }).then(x=>{
                //分页
                if(isNaN(page) || isNaN(pageSize) ||pageSize<1 || page<1 || x.length<1){
                    return {
                        count:x.length,
                        data:x,
                    };
                }
                let pageCount=x.length/pageSize;
                if(x.length%pageSize>0){
                    pageCount+=1;
                }
                //分页
                if(page>pageCount){
                    return [];
                }
                if(page){
                    return {
                        count:x.length,
                        page:page,
                        pageSize:pageSize,
                        data:x.slice((page-1)*pageSize,page*pageSize)
                    }
                }
                return {
                    count:x.length,
                    data:x,
                };
            })
        })
    }

    //删除
    static delete(dbKey,id){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            return new Promise((resolve, reject) => {
                let request=store.delete(id)
                request.onsuccess=()=>{
                    db.close()
                    resolve();
                }
                request.onerror=(err)=>{
                    db.close();
                    reject(err)
                };
            })
        })
    }
    static deleteList(dbKey,ids){
        return _openDB(dbKey).then((db)=>{
            let store = db.transaction(dbKey, 'readwrite').objectStore(dbKey);
            let list=[]
            ids.forEach(id=>list.push(new Promise((resolve, reject) => {
                let request=store.delete(id)
                request.onsuccess=()=>{
                    resolve();
                }
                request.onerror=reject
            })))
            return Promise.all(list).then(()=>db.close()).catch(db.close())
        })
    }

    //数据库是否存在
    static isExist(dbKey){
        return indexedDB.databases().then(x=>{
            return x.filter(x=>x.name===dbKey).length>0
        })
    }
    //获取表信息
    getTableInfo(dbKey){
        return _openDB(dbKey).then((db)=>{
            let info=db.transaction(dbKey,"readwrite").objectStore(dbKey);
            db.close();
            return Promise.resolve(info);
        })
    }
    //打开，没有则创建
    static created(dbKey,keyPath="id",autoIncrement=false){
        return auDataBase.isExist(dbKey).then(x=>{
            if(x){
                return Promise.resolve();
            }
            //创建库和表
            return new Promise((resolve, reject) => {
                let request = indexedDB.open(dbKey);
                request.onupgradeneeded=(e)=>{
                    let db=e.target.result;
                    db.createObjectStore(dbKey, {keyPath:keyPath, autoIncrement:autoIncrement});
                    resolve(db)
                };
                request.onerror=reject;
            });
        })
    }
    //删除库
    static remove(dbKey){
        indexedDB.deleteDatabase(dbKey);
    }

}
const _dbs={};

//初始化方法
function init(dbKey){
    if(_dbs[dbKey]){
        return _dbs[dbKey];
    }
    _dbs[dbKey]=new auDataBase(dbKey)
    return _dbs[dbKey];
}

init.DataBase=auDataBase;

window.TestIndexDB=init;
export default init;






